/**
 * 
 */
package com.nervytech.tutorcruise.spring.controller;

import java.util.Date;
import java.util.LinkedList;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.nervytech.tutorcruise.application.util.IConstants;
import com.nervytech.tutorcruise.application.util.UUIDGenerator;
import com.nervytech.tutorcruise.db.dao.model.User;
import com.nervytech.tutorcruise.db.dao.model.UserUuid;
import com.nervytech.tutorcruise.db.enums.MessageTypeEnum;
import com.nervytech.tutorcruise.db.enums.UserStatusEnum;
import com.nervytech.tutorcruise.db.enums.UuidTypeEnum;
import com.nervytech.tutorcruise.db.service.interfaces.IUserService;
import com.nervytech.tutorcruise.db.service.interfaces.IUserUuidService;
import com.nervytech.tutorcruise.spring.common.form.ForgotPwdForm;
import com.nervytech.tutorcruise.spring.common.form.LoginForm;
import com.nervytech.tutorcruise.spring.common.form.RegistrationForm;
import com.nervytech.tutorcruise.spring.common.form.ResetPwdForm;

/**
 * @author ADMIN
 * 
 */
@Controller
@RequestMapping("/auth/login")
public class LoginController {

	private static final Logger logger = LoggerFactory
			.getLogger(LoginController.class);

	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private SaltSource saltSource;

	@Autowired
	private IUserService userService;

	@Autowired
	private IUserUuidService usrUuidService;

	@RequestMapping(method = RequestMethod.GET)
	public String showHome(Map model, HttpServletRequest request) {

		LoginForm loginForm = new LoginForm();

		if (request.getParameter("message") != null
				&& request.getParameter("message").equalsIgnoreCase("failed")) {
			loginForm.setMessage("Invalid Email address or Password");
			loginForm.setMessageType(MessageTypeEnum.ERROR.name());
		}

		model.put("loginForm", loginForm);

		return "login";
	}

	@RequestMapping(params = "action=forgotpwd", method = RequestMethod.GET)
	public String forgotPassword(Map model) {

		ForgotPwdForm form = new ForgotPwdForm();
		model.put("forgotPwdForm", form);

		return "forgotpwd";
	}

	@RequestMapping(value = "/change/pwd", method = RequestMethod.POST)
	public String changePwd(ResetPwdForm resetForm, BindingResult result,
			Map model, HttpServletRequest request) {

		ValidationUtils.rejectIfEmptyOrWhitespace(result, "password",
				"NotEmpty.registrationForm.password",
				"Password must not be empty.");
		ValidationUtils.rejectIfEmptyOrWhitespace(result, "confirmPassword",
				"NotEmpty.registrationForm.confirmPassword",
				"Confirm password must not be empty.");

		if (!(resetForm.getPassword()).equals(resetForm.getConfirmPassword())) {
			result.rejectValue("confirmPassword",
					"matchingPassword.profileForm.password",
					"Password and Confirm Password does not match.");
		}

		if (result.hasErrors()) {
			return "changepwd";
		}

		UserUuid usrUuid = new UserUuid();
		usrUuid.setUuid(resetForm.getUuId());
		usrUuid.setUserId(resetForm.getUserId());
		usrUuid.setType(UuidTypeEnum.PWDRESET.getType());

		try {

			boolean isValid = usrUuidService.isValidUuid(usrUuid,
					resetForm.getEmail());

			if (isValid) {
				usrUuidService.deleteUuid(resetForm.getUuId());

				// Update encrypted password ........
				UserDetails userDetails = userDetailsService
						.loadUserByUsername(resetForm.getEmail());

				String saltedPassword = passwordEncoder.encodePassword(
						resetForm.getPassword(),
						saltSource.getSalt(userDetails));

				userService.updatePassword(resetForm.getUserId(),
						saltedPassword);

				LoginForm form = new LoginForm();
				form.setMessage("Password updated successfully");
				form.setMessageType(MessageTypeEnum.SUCCESS.name());
				model.put("loginForm", form);
				return "login";
			} else {
				ResetPwdForm form = new ResetPwdForm();
				form.setMessage("Oops !!! Your request can not be completed. Please check the request or contact our support at "
						+ IConstants.SUPPORT_EMAIL);
				form.setMessageType(MessageTypeEnum.ERROR.name());
				model.put("resetPwdForm", form);
				return "resetpwd";
			}

		} catch (Exception e) {
			ResetPwdForm form = new ResetPwdForm();
			form.setMessage("Oops !!! Your request can not be completed. Please check the request or contact our support at "
					+ IConstants.SUPPORT_EMAIL);
			form.setMessageType(MessageTypeEnum.ERROR.name());
			model.put("resetPwdForm", form);
			return "resetpwd";
		}

	}

	@RequestMapping(value = "/reset", method = RequestMethod.POST)
	public String sendResetMail(ForgotPwdForm forgotForm, BindingResult result,
			Map model, HttpServletRequest request) {

		ValidationUtils
				.rejectIfEmptyOrWhitespace(result, "emailId",
						"NotEmpty.registrationForm.emailId",
						"Email must not be empty.");

		if (result.hasErrors()) {
			return "forgotpwd";
		}
		
		try {

		User user = userService.getUserByEmail(forgotForm.getEmail());

		if (user == null) {
			result.rejectValue("emailId",
					"matchingPassword.registrationForm.emailId",
					"Oops !!!, The user does not exist in our system.");
			return "forgotpwd";
		} else if (user.getUserStatus() != UserStatusEnum.ENABLED.getStatus()) {
			result.rejectValue("emailId",
					"matchingPassword.registrationForm.emailId",
					"Oops !!!, The user is not yet Activated.");
			return "forgotpwd";
		}

		UserUuid usrUuid = new UserUuid();
		usrUuid.setUuid(UUIDGenerator.getTimeUUID().toString());
		usrUuid.setUserId(user.getUserId());
		usrUuid.setType(UuidTypeEnum.PWDRESET.getType());
		usrUuid.setCreatedTime(new Date());

		usrUuidService.saveUuid(usrUuid);

		logger.info("Password Reset mail UUID : " + usrUuid.getUuid()
				+ " User : " + user.getEmail());

		String resetUrl = request.getScheme() + "://" + request.getServerName()
				+ ":" + request.getServerPort() + "/"
				+ request.getContextPath() + "/"
				+ "auth/login/reset/confirm/email/EMAIL_ID/id/USERID/hash/UUID";

		resetUrl = resetUrl.replaceAll("EMAIL_ID", user.getEmail());
		resetUrl = resetUrl.replaceAll("UUID", usrUuid.getUuid());
		resetUrl = resetUrl.replaceAll("USERID", user.getUserId() + "");

		String content = "Hi "
				+ user.getFullName()
				+ "\n Please click the following link for resetting your password.\n "
				+ resetUrl;

		logger.debug("Sendig mail for password reset : " + user.getEmail());

		LinkedList<String> recipientsList = new LinkedList<String>();
		recipientsList.add(user.getEmail().trim());

		// TODO : Code to send Email ....

		ForgotPwdForm form = new ForgotPwdForm();
		form.setMessage("Password reset mail has been sent to your emailid");
		form.setMessageType(MessageTypeEnum.SUCCESS.name());
		model.put("forgotPwdForm", form);
		
		} catch (Exception e) {
			ForgotPwdForm form = new ForgotPwdForm();
			form.setMessage("Oops !!! Your request can not be completed. Please check the request or contact our support at " + IConstants.SUPPORT_EMAIL);
			form.setMessageType(MessageTypeEnum.ERROR.name());
			model.put("forgotPwdForm", form);
		}
		
		return "forgotpwd";
	}

	@RequestMapping(value = "/reset/confirm/email/{emailId}/id/{usrId}/hash/{uuId}", method = RequestMethod.GET)
	public String resetPassword(@PathVariable String emailId,
			@PathVariable String usrId, @PathVariable String uuId, Map model) {

		String userId = null;

		UserUuid usrUuid = new UserUuid();
		usrUuid.setUuid(uuId);
		usrUuid.setUserId(Long.parseLong(usrId));
		usrUuid.setType(UuidTypeEnum.REGCONFIRM.getType());

		boolean isValid = usrUuidService.isValidUuid(usrUuid, emailId);

		if (isValid) {

			ResetPwdForm resetForm = new ResetPwdForm();
			resetForm.setEmail(emailId);
			resetForm.setUuId(uuId);
			resetForm.setUserId(Long.parseLong(userId));
			model.put("resetPwdForm", resetForm);
		} else {
			RegistrationForm regForm = new RegistrationForm();
			regForm.setMessage("Oops !!! Your request can not be completed. Please check the request or contact our support at "
					+ IConstants.SUPPORT_EMAIL);
			regForm.setMessageType(MessageTypeEnum.ERROR.name());

			model.put("registrationForm", regForm);

			return "home";
		}

		return "resetpwd";

	}
}
